Convert GailTextCell to GtkTextCellAccessible
authorMatthias Clasen <mclasen@redhat.com>
Sun, 10 Jul 2011 03:26:59 +0000 (23:26 -0400)
committerMatthias Clasen <mclasen@redhat.com>
Sun, 10 Jul 2011 03:57:16 +0000 (23:57 -0400)
gtk/a11y/Makefile.am
gtk/a11y/gailtextcell.c [deleted file]
gtk/a11y/gailtextcell.h [deleted file]
gtk/a11y/gtktextcellaccessible.c [new file with mode: 0644]
gtk/a11y/gtktextcellaccessible.h [new file with mode: 0644]
gtk/a11y/gtktreeviewaccessible.c

index 1d54a7c8f0353f95581241f0ca0376e7333749c5..5b16442ee814ee8d39a112a23180b0bf6419ba85 100644 (file)
@@ -43,7 +43,7 @@ gail_c_sources =                      \
        gtkstatusbaraccessible.c        \
        gtksubmenuitemaccessible.c      \
        gtkswitchaccessible.c           \
-       gailtextcell.c                  \
+       gtktextcellaccessible.c         \
        gtktextviewaccessible.c         \
        gtktogglebuttonaccessible.c     \
        gtktoplevelaccessible.c         \
@@ -95,7 +95,7 @@ gail_private_h_sources =              \
        gtkstatusbaraccessible.h        \
        gtksubmenuitemaccessible.h      \
        gtkswitchaccessible.h           \
-       gailtextcell.h                  \
+       gtktextcellaccessible.h         \
        gtktextviewaccessible.h         \
        gtktogglebuttonaccessible.h     \
        gtktoplevelaccessible.h         \
diff --git a/gtk/a11y/gailtextcell.c b/gtk/a11y/gailtextcell.c
deleted file mode 100644 (file)
index d36496e..0000000
+++ /dev/null
@@ -1,821 +0,0 @@
-/* GAIL - The GNOME Accessibility Enabling Library
- * Copyright 2001 Sun Microsystems Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#include "config.h"
-#include <string.h>
-#include <gtk/gtk.h>
-#include "../gtkpango.h"
-#include "gailtextcell.h"
-#include "gtkcontainercellaccessible.h"
-#include "gailcellparent.h"
-
-static void      gail_text_cell_class_init             (GailTextCellClass *klass);
-static void      gail_text_cell_init                   (GailTextCell   *text_cell);
-static void      gail_text_cell_finalize               (GObject        *object);
-
-static const gchar* gail_text_cell_get_name    (AtkObject      *atk_obj);
-
-static void      atk_text_interface_init               (AtkTextIface   *iface);
-
-/* atktext.h */
-
-static gchar*    gail_text_cell_get_text               (AtkText        *text,
-                                                       gint            start_pos,
-                                                       gint            end_pos);
-static gunichar gail_text_cell_get_character_at_offset (AtkText        *text,
-                                                        gint           offset);
-static gchar*  gail_text_cell_get_text_before_offset   (AtkText        *text,
-                                                        gint           offset,
-                                                        AtkTextBoundary boundary_type,
-                                                        gint           *start_offset,
-                                                        gint           *end_offset);
-static gchar*  gail_text_cell_get_text_at_offset       (AtkText        *text,
-                                                        gint           offset,
-                                                        AtkTextBoundary boundary_type,
-                                                        gint           *start_offset,
-                                                        gint           *end_offset);
-static gchar*  gail_text_cell_get_text_after_offset    (AtkText        *text,
-                                                        gint           offset,
-                                                        AtkTextBoundary boundary_type,
-                                                        gint           *start_offset,
-                                                        gint           *end_offset);
-static gint      gail_text_cell_get_character_count    (AtkText        *text);
-static gint      gail_text_cell_get_caret_offset       (AtkText        *text);
-static gboolean  gail_text_cell_set_caret_offset       (AtkText        *text,
-                                                        gint           offset);
-static void      gail_text_cell_get_character_extents  (AtkText        *text,
-                                                        gint           offset,
-                                                        gint           *x,
-                                                        gint           *y,
-                                                        gint           *width,
-                                                        gint           *height,
-                                                        AtkCoordType   coords);
-static gint      gail_text_cell_get_offset_at_point    (AtkText        *text,
-                                                        gint           x,
-                                                        gint           y,
-                                                        AtkCoordType   coords);
-static AtkAttributeSet* gail_text_cell_get_run_attributes 
-                                                        (AtkText       *text,
-                                                        gint           offset,
-                                                        gint           *start_offset,      
-                                                        gint           *end_offset); 
-static AtkAttributeSet* gail_text_cell_get_default_attributes 
-                                                        (AtkText        *text);
-
-static GtkWidget*       get_widget                      (GailTextCell *cell);
-static PangoLayout*     create_pango_layout             (GailTextCell *cell);
-static void             add_attr                        (PangoAttrList  *attr_list,
-                                                         PangoAttribute *attr);
-
-/* Misc */
-
-static gboolean gail_text_cell_update_cache            (GtkRendererCellAccessible *cell,
-                                                        gboolean       emit_change_signal);
-
-gchar *gail_text_cell_property_list[] = {
-  /* Set font_desc first since it resets other values if it is NULL */
-  "font_desc",
-  "attributes",
-  "background-gdk",
-  "editable",
-  "family",
-  "foreground-gdk",
-  "rise",
-  "scale",
-  "size",
-  "size-points",
-  "stretch",
-  "strikethrough",
-  "style",
-  "text",
-  "underline",
-  "variant",
-  "weight",
-
-  /* Also need the sets */
-  "background-set",
-  "editable-set",
-  "family-set",
-  "foreground-set",
-  "rise-set",
-  "scale-set",
-  "size-set",
-  "stretch-set",
-  "strikethrough-set",
-  "style-set",
-  "underline-set",
-  "variant-set",
-  "weight-set",
-  NULL
-};
-
-G_DEFINE_TYPE_WITH_CODE (GailTextCell, gail_text_cell, GTK_TYPE_RENDERER_CELL_ACCESSIBLE,
-                         G_IMPLEMENT_INTERFACE (ATK_TYPE_TEXT, atk_text_interface_init))
-
-static void 
-gail_text_cell_class_init (GailTextCellClass *klass)
-{
-  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
-  AtkObjectClass *atk_object_class = ATK_OBJECT_CLASS (klass);
-  GtkRendererCellAccessibleClass *renderer_cell_class = GTK_RENDERER_CELL_ACCESSIBLE_CLASS (klass);
-
-  renderer_cell_class->update_cache = gail_text_cell_update_cache;
-  renderer_cell_class->property_list = gail_text_cell_property_list;
-
-  atk_object_class->get_name = gail_text_cell_get_name;
-
-  gobject_class->finalize = gail_text_cell_finalize;
-}
-
-/* atktext.h */
-
-static void
-gail_text_cell_init (GailTextCell *text_cell)
-{
-  text_cell->cell_text = NULL;
-  text_cell->caret_pos = 0;
-  text_cell->cell_length = 0;
-  atk_state_set_add_state (GTK_CELL_ACCESSIBLE (text_cell)->state_set,
-                           ATK_STATE_SINGLE_LINE);
-}
-
-AtkObject* 
-gail_text_cell_new (void)
-{
-  GObject *object;
-  AtkObject *atk_object;
-  GtkRendererCellAccessible *cell;
-
-  object = g_object_new (GAIL_TYPE_TEXT_CELL, NULL);
-
-  g_return_val_if_fail (object != NULL, NULL);
-
-  atk_object = ATK_OBJECT (object);
-  atk_object->role = ATK_ROLE_TABLE_CELL;
-
-  cell = GTK_RENDERER_CELL_ACCESSIBLE(object);
-
-  cell->renderer = gtk_cell_renderer_text_new ();
-  g_object_ref_sink (cell->renderer);
-  return atk_object;
-}
-
-static void
-gail_text_cell_finalize (GObject            *object)
-{
-  GailTextCell *text_cell = GAIL_TEXT_CELL (object);
-
-  g_free (text_cell->cell_text);
-
-  G_OBJECT_CLASS (gail_text_cell_parent_class)->finalize (object);
-}
-
-static const gchar*
-gail_text_cell_get_name (AtkObject *atk_obj)
-{
-  if (atk_obj->name)
-    return atk_obj->name;
-  else
-    {
-      GailTextCell *text_cell = GAIL_TEXT_CELL (atk_obj);
-
-      return text_cell->cell_text;
-    }
-}
-
-static gboolean
-gail_text_cell_update_cache (GtkRendererCellAccessible *cell,
-                             gboolean         emit_change_signal)
-{
-  GailTextCell *text_cell = GAIL_TEXT_CELL (cell);
-  AtkObject *obj = ATK_OBJECT (cell);
-  gboolean rv = FALSE;
-  gint temp_length;
-  gchar *new_cache;
-
-  g_object_get (G_OBJECT (cell->renderer), "text", &new_cache, NULL);
-
-  if (text_cell->cell_text)
-    {
-     /*
-      * If the new value is NULL and the old value isn't NULL, then the
-      * value has changed.
-      */
-      if (new_cache == NULL ||
-          strcmp (text_cell->cell_text, new_cache))
-        {
-          g_free (text_cell->cell_text);
-          temp_length = text_cell->cell_length;
-          text_cell->cell_text = NULL;
-          text_cell->cell_length = 0;
-          if (emit_change_signal)
-            {
-              g_signal_emit_by_name (cell, "text_changed::delete", 0, temp_length);
-              if (obj->name == NULL)
-                g_object_notify (G_OBJECT (obj), "accessible-name");
-            }
-          if (new_cache)
-            rv = TRUE;
-        }
-    }
-  else
-    rv = TRUE;
-
-  if (rv)
-    {
-      if (new_cache == NULL)
-        {
-          text_cell->cell_text = g_strdup ("");
-          text_cell->cell_length = 0;
-        }
-      else
-        {
-          text_cell->cell_text = g_strdup (new_cache);
-          text_cell->cell_length = g_utf8_strlen (new_cache, -1);
-        }
-    }
-
-  g_free (new_cache);
-
-  if (rv)
-    {
-      if (emit_change_signal)
-        {
-          g_signal_emit_by_name (cell, "text_changed::insert",
-                                0, text_cell->cell_length);
-
-          if (obj->name == NULL)
-            g_object_notify (G_OBJECT (obj), "accessible-name");
-        }
-    }
-  return rv;
-}
-
-static void
-atk_text_interface_init (AtkTextIface *iface)
-{
-  iface->get_text = gail_text_cell_get_text;
-  iface->get_character_at_offset = gail_text_cell_get_character_at_offset;
-  iface->get_text_before_offset = gail_text_cell_get_text_before_offset;
-  iface->get_text_at_offset = gail_text_cell_get_text_at_offset;
-  iface->get_text_after_offset = gail_text_cell_get_text_after_offset;
-  iface->get_character_count = gail_text_cell_get_character_count;
-  iface->get_caret_offset = gail_text_cell_get_caret_offset;
-  iface->set_caret_offset = gail_text_cell_set_caret_offset;
-  iface->get_run_attributes = gail_text_cell_get_run_attributes;
-  iface->get_default_attributes = gail_text_cell_get_default_attributes;
-  iface->get_character_extents = gail_text_cell_get_character_extents;
-  iface->get_offset_at_point = gail_text_cell_get_offset_at_point;
-}
-
-static gchar* 
-gail_text_cell_get_text (AtkText *atk_text, 
-                         gint    start_pos,
-                         gint    end_pos)
-{
-  gchar *text;
-
-  text = GAIL_TEXT_CELL (atk_text)->cell_text;
-  if (text)
-    return g_utf8_substring (text, start_pos, end_pos > -1 ? end_pos : g_utf8_strlen (text, -1));
-  else
-    return g_strdup ("");
-}
-
-static gchar* 
-gail_text_cell_get_text_before_offset (AtkText         *atk_text,
-                                       gint            offset,
-                                       AtkTextBoundary boundary_type,
-                                       gint            *start_offset,
-                                       gint            *end_offset)
-{
-  PangoLayout *layout;
-  gchar *text;
-
-  layout = create_pango_layout (GAIL_TEXT_CELL (atk_text));
-  text = _gtk_pango_get_text_before (layout, boundary_type, offset, start_offset, end_offset);
-  g_object_unref (layout);
-
-  return text;
-}
-
-static gchar* 
-gail_text_cell_get_text_at_offset (AtkText         *atk_text,
-                                   gint            offset,
-                                   AtkTextBoundary boundary_type,
-                                   gint            *start_offset,
-                                   gint            *end_offset)
-{
-  PangoLayout *layout;
-  gchar *text;
-
-  layout = create_pango_layout (GAIL_TEXT_CELL (atk_text));
-  text = _gtk_pango_get_text_at (layout, boundary_type, offset, start_offset, end_offset);
-  g_object_unref (layout);
-
-  return text;
-}
-
-static gchar* 
-gail_text_cell_get_text_after_offset (AtkText         *atk_text,
-                                      gint            offset,
-                                      AtkTextBoundary boundary_type,
-                                      gint            *start_offset,
-                                      gint            *end_offset)
-{
-  PangoLayout *layout;
-  gchar *text;
-
-  layout = create_pango_layout (GAIL_TEXT_CELL (atk_text));
-  text = _gtk_pango_get_text_after (layout, boundary_type, offset, start_offset, end_offset);
-  g_object_unref (layout);
-
-  return text;
-}
-
-static gint 
-gail_text_cell_get_character_count (AtkText *text)
-{
-  if (GAIL_TEXT_CELL (text)->cell_text != NULL)
-    return GAIL_TEXT_CELL (text)->cell_length;
-  else
-    return 0;
-}
-
-static gint 
-gail_text_cell_get_caret_offset (AtkText *text)
-{
-  return GAIL_TEXT_CELL (text)->caret_pos;
-}
-
-static gboolean 
-gail_text_cell_set_caret_offset (AtkText *text,
-                                 gint    offset)
-{
-  GailTextCell *text_cell = GAIL_TEXT_CELL (text);
-
-  if (text_cell->cell_text == NULL)
-    return FALSE;
-  else
-    {
-
-      /* Only set the caret within the bounds and if it is to a new position. */
-      if (offset >= 0 && 
-          offset <= text_cell->cell_length &&
-          offset != text_cell->caret_pos)
-        {
-          text_cell->caret_pos = offset;
-
-          /* emit the signal */
-          g_signal_emit_by_name (text, "text_caret_moved", offset);
-          return TRUE;
-        }
-      else
-        return FALSE;
-    }
-}
-
-static AtkAttributeSet*
-gail_text_cell_get_run_attributes (AtkText *text,
-                                  gint     offset,
-                                  gint     *start_offset,
-                                  gint     *end_offset)
-{
-  AtkAttributeSet *attrib_set = NULL;
-  PangoLayout *layout;
-
-  layout = create_pango_layout (GAIL_TEXT_CELL (text));
-  attrib_set = _gtk_pango_get_run_attributes  (NULL, layout, offset, start_offset, end_offset);
-  g_object_unref (G_OBJECT (layout));
-
-  return attrib_set;
-}
-
-static AtkAttributeSet *
-add_attribute (AtkAttributeSet  *attributes,
-               AtkTextAttribute  attr,
-               const gchar      *value)
-{
-  AtkAttribute *at;
-
-  at = g_new (AtkAttribute, 1);
-  at->name = g_strdup (atk_text_attribute_get_name (attr));
-  at->value = g_strdup (value);
-
-  return g_slist_prepend (attributes, at);
-}
-
-static AtkAttributeSet*
-gail_text_cell_get_default_attributes (AtkText *text)
-{
-  AtkAttributeSet *attrib_set = NULL;
-  PangoLayout *layout;
-  GtkWidget *widget;
-
-  layout = create_pango_layout (GAIL_TEXT_CELL (text));
-  widget = get_widget (GAIL_TEXT_CELL (text));
-
-  attrib_set = add_attribute (attrib_set, ATK_TEXT_ATTR_DIRECTION,
-                   atk_text_attribute_get_value (ATK_TEXT_ATTR_DIRECTION,
-                                                 gtk_widget_get_direction (widget)));
-  attrib_set = _gtk_pango_get_default_attributes (NULL, layout);
-
-  attrib_set = _gtk_style_context_get_attributes (attrib_set,
-                                                  gtk_widget_get_style_context (widget),
-                                                  gtk_widget_get_state_flags (widget));
-
-  g_object_unref (G_OBJECT (layout));
-
-  return attrib_set;
-}
-
-GtkWidget *
-get_widget (GailTextCell *text)
-{
-  AtkObject *parent;
-
-  parent = atk_object_get_parent (ATK_OBJECT (text));
-  if (GTK_IS_CONTAINER_CELL_ACCESSIBLE (parent))
-    parent = atk_object_get_parent (parent);
-
-  return gtk_accessible_get_widget (GTK_ACCESSIBLE (parent));
-}
-
-/* 
- * This function is used by gail_text_cell_get_offset_at_point()
- * and gail_text_cell_get_character_extents(). There is no 
- * cached PangoLayout for gailtextcell so we must create a temporary
- * one using this function.
- */ 
-static PangoLayout*
-create_pango_layout (GailTextCell *text)
-{
-  GdkRGBA *foreground_rgba;
-  PangoAttrList *attr_list, *attributes;
-  PangoLayout *layout;
-  PangoUnderline uline, underline;
-  PangoFontMask mask;
-  PangoFontDescription *font_desc;
-  gboolean foreground_set, strikethrough_set, strikethrough;
-  gboolean scale_set, underline_set, rise_set;
-  gchar *renderer_text;
-  gdouble scale;
-  gint rise;
-  GtkRendererCellAccessible *gail_renderer;
-  GtkCellRendererText *gtk_renderer;
-
-  gail_renderer = GTK_RENDERER_CELL_ACCESSIBLE (text);
-  gtk_renderer = GTK_CELL_RENDERER_TEXT (gail_renderer->renderer);
-
-  g_object_get (gtk_renderer,
-                "text", &renderer_text,
-                "attributes", &attributes,
-                "foreground-set", &foreground_set,
-                "foreground-rgba", &foreground_rgba,
-                "strikethrough-set", &strikethrough_set,
-                "strikethrough", &strikethrough,
-                "font-desc", &font_desc,
-                "scale-set", &scale_set,
-                "scale", &scale,
-                "underline-set", &underline_set,
-                "underline", &underline,
-                "rise-set", &rise_set,
-                "rise", &rise,
-                NULL);
-
-  layout = gtk_widget_create_pango_layout (get_widget (text), renderer_text);
-
-  if (attributes)
-    attr_list = pango_attr_list_copy (attributes);
-  else
-    attr_list = pango_attr_list_new ();
-
-  if (foreground_set)
-    {
-      add_attr (attr_list, pango_attr_foreground_new (foreground_rgba->red * 65535,
-                                                      foreground_rgba->green * 65535,
-                                                      foreground_rgba->blue * 65535));
-    }
-
-  if (strikethrough_set)
-    add_attr (attr_list,
-              pango_attr_strikethrough_new (strikethrough));
-
-  mask = pango_font_description_get_set_fields (font_desc);
-
-  if (mask & PANGO_FONT_MASK_FAMILY)
-    add_attr (attr_list,
-      pango_attr_family_new (pango_font_description_get_family (font_desc)));
-
-  if (mask & PANGO_FONT_MASK_STYLE)
-    add_attr (attr_list, pango_attr_style_new (pango_font_description_get_style (font_desc)));
-
-  if (mask & PANGO_FONT_MASK_VARIANT)
-    add_attr (attr_list, pango_attr_variant_new (pango_font_description_get_variant (font_desc)));
-
-  if (mask & PANGO_FONT_MASK_WEIGHT)
-    add_attr (attr_list, pango_attr_weight_new (pango_font_description_get_weight (font_desc)));
-
-  if (mask & PANGO_FONT_MASK_STRETCH)
-    add_attr (attr_list, pango_attr_stretch_new (pango_font_description_get_stretch (font_desc)));
-
-  if (mask & PANGO_FONT_MASK_SIZE)
-    add_attr (attr_list, pango_attr_size_new (pango_font_description_get_size (font_desc)));
-
-  if (scale_set && scale != 1.0)
-    add_attr (attr_list, pango_attr_scale_new (scale));
-
-  if (underline_set)
-    uline = underline;
-  else
-    uline = PANGO_UNDERLINE_NONE;
-
-  if (uline != PANGO_UNDERLINE_NONE)
-    add_attr (attr_list,
-              pango_attr_underline_new (underline));
-
-  if (rise_set)
-    add_attr (attr_list, pango_attr_rise_new (rise));
-
-  pango_layout_set_attributes (layout, attr_list);
-  pango_layout_set_width (layout, -1);
-  pango_attr_list_unref (attr_list);
-
-  pango_font_description_free (font_desc);
-  pango_attr_list_unref (attributes);
-  g_free (renderer_text);
-  gdk_rgba_free (foreground_rgba);
-
-  return layout;
-}
-
-static void 
-add_attr (PangoAttrList  *attr_list,
-         PangoAttribute *attr)
-{
-  attr->start_index = 0;
-  attr->end_index = G_MAXINT;
-  pango_attr_list_insert (attr_list, attr);
-}
-
-
-static void
-get_origins (GtkWidget *widget,
-             gint      *x_window,
-             gint      *y_window,
-             gint      *x_toplevel,
-             gint      *y_toplevel)
-{
-  GdkWindow *window;
-
-  if (GTK_IS_TREE_VIEW (widget))
-    window = gtk_tree_view_get_bin_window (GTK_TREE_VIEW (widget));
-  else
-    window = gtk_widget_get_window (widget);
-
-  gdk_window_get_origin (window, x_window, y_window);
-  window = gdk_window_get_toplevel (gtk_widget_get_window (widget));
-  gdk_window_get_origin (window, x_toplevel, y_toplevel);
-}
-
-static void      
-gail_text_cell_get_character_extents (AtkText          *text,
-                                      gint             offset,
-                                      gint             *x,
-                                      gint             *y,
-                                      gint             *width,
-                                      gint             *height,
-                                      AtkCoordType     coords)
-{
-  GtkRendererCellAccessible *gail_renderer; 
-  GtkRequisition min_size;
-  GtkCellRendererText *gtk_renderer;
-  GdkRectangle rendered_rect;
-  GtkWidget *widget;
-  AtkObject *parent;
-  PangoRectangle char_rect;
-  PangoLayout *layout;
-  gchar *renderer_text;
-  gfloat xalign, yalign;
-  gint x_offset, y_offset, index;
-  gint xpad, ypad;
-  gint x_window, y_window, x_toplevel, y_toplevel;
-
-  if (!GAIL_TEXT_CELL (text)->cell_text)
-    {
-      *x = *y = *height = *width = 0;
-      return;
-    }
-  if (offset < 0 || offset >= GAIL_TEXT_CELL (text)->cell_length)
-    {
-      *x = *y = *height = *width = 0;
-      return;
-    }
-  gail_renderer = GTK_RENDERER_CELL_ACCESSIBLE (text);
-  gtk_renderer = GTK_CELL_RENDERER_TEXT (gail_renderer->renderer);
-  /*
-   * Thus would be inconsistent with the cache
-   */
-  g_object_get (gtk_renderer, "text", &renderer_text, NULL);
-  if (text == NULL)
-    {
-      g_free (renderer_text);
-      return;
-    }
-
-  parent = atk_object_get_parent (ATK_OBJECT (text));
-  if (GTK_IS_CONTAINER_CELL_ACCESSIBLE (parent))
-    parent = atk_object_get_parent (parent);
-  widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (parent));
-  g_return_if_fail (GAIL_IS_CELL_PARENT (parent));
-  gail_cell_parent_get_cell_area (GAIL_CELL_PARENT (parent), GTK_CELL_ACCESSIBLE (text),
-                                  &rendered_rect);
-
-  gtk_cell_renderer_get_preferred_size (GTK_CELL_RENDERER (gtk_renderer),
-                                        widget,
-                                        &min_size, NULL);
-
-  gtk_cell_renderer_get_alignment (GTK_CELL_RENDERER (gtk_renderer), &xalign, &yalign);
-  if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
-    xalign = 1.0 - xalign;
-  x_offset = MAX (0, xalign * (rendered_rect.width - min_size.width));
-  y_offset = MAX (0, yalign * (rendered_rect.height - min_size.height));
-
-  layout = create_pango_layout (GAIL_TEXT_CELL (text));
-
-  index = g_utf8_offset_to_pointer (renderer_text, offset) - renderer_text;
-  pango_layout_index_to_pos (layout, index, &char_rect);
-
-  gtk_cell_renderer_get_padding (gail_renderer->renderer, &xpad, &ypad);
-
-  get_origins (widget, &x_window, &y_window, &x_toplevel, &y_toplevel);
-
-  *x = (char_rect.x / PANGO_SCALE) + x_offset + rendered_rect.x + xpad + x_window;
-  *y = (char_rect.y / PANGO_SCALE) + y_offset + rendered_rect.y + ypad + y_window;
-  if (coords == ATK_XY_WINDOW)
-    {
-      *x -= x_toplevel;
-      *y -= y_toplevel;
-    }
-  else if (coords != ATK_XY_SCREEN)
-    {
-      *x = 0;
-      *y = 0;
-      *height = 0;
-      *width = 0;
-      return;
-    }
-  *height = char_rect.height / PANGO_SCALE;
-  *width = char_rect.width / PANGO_SCALE;
-
-  g_free (renderer_text);
-  g_object_unref (layout);
-} 
-
-static gint      
-gail_text_cell_get_offset_at_point (AtkText          *text,
-                                    gint             x,
-                                    gint             y,
-                                    AtkCoordType     coords)
-{
-  AtkObject *parent;
-  GtkRendererCellAccessible *gail_renderer; 
-  GtkCellRendererText *gtk_renderer;
-  GtkRequisition min_size;
-  GtkWidget *widget;
-  GdkRectangle rendered_rect;
-  PangoLayout *layout;
-  gchar *renderer_text;
-  gfloat xalign, yalign;
-  gint x_offset, y_offset, index;
-  gint xpad, ypad;
-  gint x_window, y_window, x_toplevel, y_toplevel;
-  gint x_temp, y_temp;
-  gboolean ret;
-
-  if (!GAIL_TEXT_CELL (text)->cell_text)
-    return -1;
-
-  gail_renderer = GTK_RENDERER_CELL_ACCESSIBLE (text);
-  gtk_renderer = GTK_CELL_RENDERER_TEXT (gail_renderer->renderer);
-  parent = atk_object_get_parent (ATK_OBJECT (text));
-
-  g_object_get (gtk_renderer, "text", &renderer_text, NULL);
-  if (text == NULL)
-    {
-      g_free (renderer_text);
-      return -1;
-    }
-
-  if (GTK_IS_CONTAINER_CELL_ACCESSIBLE (parent))
-    parent = atk_object_get_parent (parent);
-
-  widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (parent));
-
-  g_return_val_if_fail (GAIL_IS_CELL_PARENT (parent), -1);
-  gail_cell_parent_get_cell_area (GAIL_CELL_PARENT (parent), GTK_CELL_ACCESSIBLE (text),
-                                  &rendered_rect);
-
-  gtk_cell_renderer_get_preferred_size (GTK_CELL_RENDERER (gtk_renderer),
-                                        widget,
-                                        &min_size, NULL);
-  gtk_cell_renderer_get_alignment (GTK_CELL_RENDERER (gtk_renderer), &xalign, &yalign);
-  if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
-    xalign = 1.0 - xalign;
-  x_offset = MAX (0, xalign * (rendered_rect.width - min_size.width));
-  y_offset = MAX (0, yalign * (rendered_rect.height - min_size.height));
-
-  layout = create_pango_layout (GAIL_TEXT_CELL (text));
-
-  gtk_cell_renderer_get_padding (gail_renderer->renderer, &xpad, &ypad);
-
-  get_origins (widget, &x_window, &y_window, &x_toplevel, &y_toplevel);
-
-  x_temp =  x - (x_offset + rendered_rect.x + xpad) - x_window;
-  y_temp =  y - (y_offset + rendered_rect.y + ypad) - y_window;
-  if (coords == ATK_XY_WINDOW)
-    {
-      x_temp += x_toplevel;  
-      y_temp += y_toplevel;
-    }
-  else if (coords != ATK_XY_SCREEN)
-    index = -1;
-
-  ret = pango_layout_xy_to_index (layout, 
-                                  x_temp * PANGO_SCALE,
-                                  y_temp * PANGO_SCALE,
-                                  &index, NULL);
-  if (!ret)
-    {
-      if (x_temp < 0 || y_temp < 0)
-        index = 0;
-      else
-        index = -1; 
-    }
-
-  g_object_unref (layout);
-  if (index == -1)
-    {
-      if (coords == ATK_XY_WINDOW || coords == ATK_XY_SCREEN)
-        {
-          glong length;
-
-          length = g_utf8_strlen (renderer_text, -1);
-          g_free (renderer_text);
-
-          return length;
-        }
-
-      g_free (renderer_text);
-
-      return index;  
-    }
-  else
-    {
-      glong offset;
-
-      offset = g_utf8_pointer_to_offset (renderer_text,
-                                         renderer_text + index);
-      g_free (renderer_text);
-
-      return offset;
-    }
-}
-
-static gunichar 
-gail_text_cell_get_character_at_offset (AtkText       *text,
-                                        gint          offset)
-{
-  gchar *index;
-  gchar *string;
-
-  string = GAIL_TEXT_CELL(text)->cell_text;
-
-  if (!string)
-    return '\0';
-
-  if (offset >= g_utf8_strlen (string, -1))
-    return '\0';
-
-  index = g_utf8_offset_to_pointer (string, offset);
-
-  return g_utf8_get_char (index);
-}
-
diff --git a/gtk/a11y/gailtextcell.h b/gtk/a11y/gailtextcell.h
deleted file mode 100644 (file)
index cc79887..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-/* GAIL - The GNOME Accessibility Enabling Library
- * Copyright 2001 Sun Microsystems Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#ifndef __GAIL_TEXT_CELL_H__
-#define __GAIL_TEXT_CELL_H__
-
-#include <atk/atk.h>
-#include "gtkrenderercellaccessible.h"
-
-G_BEGIN_DECLS
-
-#define GAIL_TYPE_TEXT_CELL            (gail_text_cell_get_type ())
-#define GAIL_TEXT_CELL(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GAIL_TYPE_TEXT_CELL, GailTextCell))
-#define GAIL_TEXT_CELL_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GAIL_TEXT_CELL, GailTextCellClass))
-#define GAIL_IS_TEXT_CELL(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GAIL_TYPE_TEXT_CELL))
-#define GAIL_IS_TEXT_CELL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GAIL_TYPE_TEXT_CELL))
-#define GAIL_TEXT_CELL_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GAIL_TYPE_TEXT_CELL, GailTextCellClass))
-
-typedef struct _GailTextCell                  GailTextCell;
-typedef struct _GailTextCellClass             GailTextCellClass;
-
-struct _GailTextCell
-{
-  GtkRendererCellAccessible parent;
-  gchar *cell_text;
-  gint caret_pos;
-  gint cell_length;
-};
-
-struct _GailTextCellClass
-{
-  GtkRendererCellAccessibleClass parent_class;
-};
-
-GType      gail_text_cell_get_type (void);
-AtkObject *gail_text_cell_new      (void);
-
-G_END_DECLS
-
-#endif /* __GAIL_TEXT_CELL_H__ */
diff --git a/gtk/a11y/gtktextcellaccessible.c b/gtk/a11y/gtktextcellaccessible.c
new file mode 100644 (file)
index 0000000..67f8831
--- /dev/null
@@ -0,0 +1,804 @@
+/* GAIL - The GNOME Accessibility Enabling Library
+ * Copyright 2001 Sun Microsystems Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+#include <string.h>
+#include <gtk/gtk.h>
+#include "../gtkpango.h"
+#include "gtktextcellaccessible.h"
+#include "gtkcontainercellaccessible.h"
+#include "gailcellparent.h"
+
+static const gchar* gtk_text_cell_accessible_get_name    (AtkObject      *atk_obj);
+
+
+/* atktext.h */
+
+static gchar*    gtk_text_cell_accessible_get_text                (AtkText        *text,
+                                                        gint            start_pos,
+                                                        gint            end_pos);
+static gunichar gtk_text_cell_accessible_get_character_at_offset  (AtkText        *text,
+                                                         gint           offset);
+static gchar*   gtk_text_cell_accessible_get_text_before_offset   (AtkText        *text,
+                                                         gint           offset,
+                                                         AtkTextBoundary boundary_type,
+                                                         gint           *start_offset,
+                                                         gint           *end_offset);
+static gchar*   gtk_text_cell_accessible_get_text_at_offset       (AtkText        *text,
+                                                         gint           offset,
+                                                         AtkTextBoundary boundary_type,
+                                                         gint           *start_offset,
+                                                         gint           *end_offset);
+static gchar*   gtk_text_cell_accessible_get_text_after_offset    (AtkText        *text,
+                                                         gint           offset,
+                                                         AtkTextBoundary boundary_type,
+                                                         gint           *start_offset,
+                                                         gint           *end_offset);
+static gint      gtk_text_cell_accessible_get_character_count     (AtkText        *text);
+static gint      gtk_text_cell_accessible_get_caret_offset        (AtkText        *text);
+static gboolean  gtk_text_cell_accessible_set_caret_offset        (AtkText        *text,
+                                                         gint           offset);
+static void      gtk_text_cell_accessible_get_character_extents   (AtkText        *text,
+                                                         gint           offset,
+                                                         gint           *x,
+                                                         gint           *y,
+                                                         gint           *width,
+                                                         gint           *height,
+                                                         AtkCoordType   coords);
+static gint      gtk_text_cell_accessible_get_offset_at_point     (AtkText        *text,
+                                                         gint           x,
+                                                         gint           y,
+                                                         AtkCoordType   coords);
+static AtkAttributeSet* gtk_text_cell_accessible_get_run_attributes 
+                                                        (AtkText        *text,
+                                                         gint           offset,
+                                                         gint           *start_offset,      
+                                                         gint           *end_offset); 
+static AtkAttributeSet* gtk_text_cell_accessible_get_default_attributes 
+                                                        (AtkText        *text);
+
+static GtkWidget*       get_widget                      (GtkTextCellAccessible *cell);
+static PangoLayout*     create_pango_layout             (GtkTextCellAccessible *cell);
+static void             add_attr                        (PangoAttrList  *attr_list,
+                                                         PangoAttribute *attr);
+
+/* Misc */
+
+static gboolean gtk_text_cell_accessible_update_cache             (GtkRendererCellAccessible *cell,
+                                                         gboolean       emit_change_signal);
+
+static gchar *property_list[] = {
+  /* Set font_desc first since it resets other values if it is NULL */
+  "font_desc",
+  "attributes",
+  "background-gdk",
+  "editable",
+  "family",
+  "foreground-gdk",
+  "rise",
+  "scale",
+  "size",
+  "size-points",
+  "stretch",
+  "strikethrough",
+  "style",
+  "text",
+  "underline",
+  "variant",
+  "weight",
+
+  /* Also need the sets */
+  "background-set",
+  "editable-set",
+  "family-set",
+  "foreground-set",
+  "rise-set",
+  "scale-set",
+  "size-set",
+  "stretch-set",
+  "strikethrough-set",
+  "style-set",
+  "underline-set",
+  "variant-set",
+  "weight-set",
+  NULL
+};
+
+static void atk_text_interface_init (AtkTextIface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (GtkTextCellAccessible, _gtk_text_cell_accessible, GTK_TYPE_RENDERER_CELL_ACCESSIBLE,
+                         G_IMPLEMENT_INTERFACE (ATK_TYPE_TEXT, atk_text_interface_init))
+
+
+static void
+gtk_text_cell_accessible_finalize (GObject *object)
+{
+  GtkTextCellAccessible *text_cell = GTK_TEXT_CELL_ACCESSIBLE (object);
+
+  g_free (text_cell->cell_text);
+
+  G_OBJECT_CLASS (_gtk_text_cell_accessible_parent_class)->finalize (object);
+}
+
+static const gchar *
+gtk_text_cell_accessible_get_name (AtkObject *atk_obj)
+{
+  GtkTextCellAccessible *text_cell = GTK_TEXT_CELL_ACCESSIBLE (atk_obj);
+
+  if (atk_obj->name)
+    return atk_obj->name;
+
+  return text_cell->cell_text;
+}
+
+static gboolean
+gtk_text_cell_accessible_update_cache (GtkRendererCellAccessible *cell,
+                                       gboolean                   emit_change_signal)
+{
+  GtkTextCellAccessible *text_cell = GTK_TEXT_CELL_ACCESSIBLE (cell);
+  AtkObject *obj = ATK_OBJECT (cell);
+  gboolean rv = FALSE;
+  gint temp_length;
+  gchar *text;
+
+  g_object_get (G_OBJECT (cell->renderer), "text", &text, NULL);
+
+  if (text_cell->cell_text)
+    {
+      if (text == NULL || strcmp (text_cell->cell_text, text) != 0)
+        {
+          g_free (text_cell->cell_text);
+          temp_length = text_cell->cell_length;
+          text_cell->cell_text = NULL;
+          text_cell->cell_length = 0;
+          if (emit_change_signal)
+            {
+              g_signal_emit_by_name (cell, "text_changed::delete", 0, temp_length);
+              if (obj->name == NULL)
+                g_object_notify (G_OBJECT (obj), "accessible-name");
+            }
+          if (text)
+            rv = TRUE;
+        }
+    }
+  else
+    rv = TRUE;
+
+  if (rv)
+    {
+      if (text == NULL)
+        {
+          text_cell->cell_text = g_strdup ("");
+          text_cell->cell_length = 0;
+        }
+      else
+        {
+          text_cell->cell_text = g_strdup (text);
+          text_cell->cell_length = g_utf8_strlen (text, -1);
+        }
+    }
+
+  g_free (text);
+
+  if (rv)
+    {
+      if (emit_change_signal)
+        {
+          g_signal_emit_by_name (cell, "text_changed::insert",
+                                 0, text_cell->cell_length);
+
+          if (obj->name == NULL)
+            g_object_notify (G_OBJECT (obj), "accessible-name");
+        }
+    }
+  return rv;
+}
+
+static void
+_gtk_text_cell_accessible_class_init (GtkTextCellAccessibleClass *klass)
+{
+  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+  AtkObjectClass *atk_object_class = ATK_OBJECT_CLASS (klass);
+  GtkRendererCellAccessibleClass *renderer_cell_class = GTK_RENDERER_CELL_ACCESSIBLE_CLASS (klass);
+
+  renderer_cell_class->update_cache = gtk_text_cell_accessible_update_cache;
+  renderer_cell_class->property_list = property_list;
+
+  atk_object_class->get_name = gtk_text_cell_accessible_get_name;
+
+  gobject_class->finalize = gtk_text_cell_accessible_finalize;
+}
+
+static void
+_gtk_text_cell_accessible_init (GtkTextCellAccessible *text_cell)
+{
+  text_cell->cell_text = NULL;
+  text_cell->caret_pos = 0;
+  text_cell->cell_length = 0;
+  atk_state_set_add_state (GTK_CELL_ACCESSIBLE (text_cell)->state_set,
+                           ATK_STATE_SINGLE_LINE);
+}
+
+AtkObject *
+_gtk_text_cell_accessible_new (void)
+{
+  GObject *object;
+  AtkObject *atk_object;
+  GtkRendererCellAccessible *cell;
+
+  object = g_object_new (GTK_TYPE_TEXT_CELL_ACCESSIBLE, NULL);
+
+  g_return_val_if_fail (object != NULL, NULL);
+
+  atk_object = ATK_OBJECT (object);
+  atk_object->role = ATK_ROLE_TABLE_CELL;
+
+  cell = GTK_RENDERER_CELL_ACCESSIBLE(object);
+
+  cell->renderer = gtk_cell_renderer_text_new ();
+  g_object_ref_sink (cell->renderer);
+
+  return atk_object;
+}
+
+static gchar *
+gtk_text_cell_accessible_get_text (AtkText *atk_text,
+                                   gint     start_pos,
+                                   gint     end_pos)
+{
+  gchar *text;
+
+  text = GTK_TEXT_CELL_ACCESSIBLE (atk_text)->cell_text;
+  if (text)
+    return g_utf8_substring (text, start_pos, end_pos > -1 ? end_pos : g_utf8_strlen (text, -1));
+  else
+    return g_strdup ("");
+}
+
+static gchar *
+gtk_text_cell_accessible_get_text_before_offset (AtkText         *atk_text,
+                                                 gint             offset,
+                                                 AtkTextBoundary  boundary_type,
+                                                 gint            *start_offset,
+                                                 gint            *end_offset)
+{
+  PangoLayout *layout;
+  gchar *text;
+
+  layout = create_pango_layout (GTK_TEXT_CELL_ACCESSIBLE (atk_text));
+  text = _gtk_pango_get_text_before (layout, boundary_type, offset, start_offset, end_offset);
+  g_object_unref (layout);
+
+  return text;
+}
+
+static gchar *
+gtk_text_cell_accessible_get_text_at_offset (AtkText         *atk_text,
+                                             gint             offset,
+                                             AtkTextBoundary  boundary_type,
+                                             gint            *start_offset,
+                                             gint            *end_offset)
+{
+  PangoLayout *layout;
+  gchar *text;
+
+  layout = create_pango_layout (GTK_TEXT_CELL_ACCESSIBLE (atk_text));
+  text = _gtk_pango_get_text_at (layout, boundary_type, offset, start_offset, end_offset);
+  g_object_unref (layout);
+
+  return text;
+}
+
+static gchar *
+gtk_text_cell_accessible_get_text_after_offset (AtkText         *atk_text,
+                                                gint             offset,
+                                                AtkTextBoundary  boundary_type,
+                                                gint            *start_offset,
+                                                gint            *end_offset)
+{
+  PangoLayout *layout;
+  gchar *text;
+
+  layout = create_pango_layout (GTK_TEXT_CELL_ACCESSIBLE (atk_text));
+  text = _gtk_pango_get_text_after (layout, boundary_type, offset, start_offset, end_offset);
+  g_object_unref (layout);
+
+  return text;
+}
+
+static gint
+gtk_text_cell_accessible_get_character_count (AtkText *text)
+{
+  if (GTK_TEXT_CELL_ACCESSIBLE (text)->cell_text != NULL)
+    return GTK_TEXT_CELL_ACCESSIBLE (text)->cell_length;
+  else
+    return 0;
+}
+
+static gint
+gtk_text_cell_accessible_get_caret_offset (AtkText *text)
+{
+  return GTK_TEXT_CELL_ACCESSIBLE (text)->caret_pos;
+}
+
+static gboolean
+gtk_text_cell_accessible_set_caret_offset (AtkText *text,
+                                           gint     offset)
+{
+  GtkTextCellAccessible *text_cell = GTK_TEXT_CELL_ACCESSIBLE (text);
+
+  if (text_cell->cell_text == NULL)
+    return FALSE;
+  else
+    {
+      /* Only set the caret within the bounds and if it is to a new position. */
+      if (offset >= 0 &&
+          offset <= text_cell->cell_length &&
+          offset != text_cell->caret_pos)
+        {
+          text_cell->caret_pos = offset;
+
+          /* emit the signal */
+          g_signal_emit_by_name (text, "text_caret_moved", offset);
+          return TRUE;
+        }
+      else
+        return FALSE;
+    }
+}
+
+static AtkAttributeSet *
+gtk_text_cell_accessible_get_run_attributes (AtkText *text,
+                                             gint     offset,
+                                             gint    *start_offset,
+                                             gint    *end_offset)
+{
+  AtkAttributeSet *attrib_set = NULL;
+  PangoLayout *layout;
+
+  layout = create_pango_layout (GTK_TEXT_CELL_ACCESSIBLE (text));
+  attrib_set = _gtk_pango_get_run_attributes  (NULL, layout, offset, start_offset, end_offset);
+  g_object_unref (G_OBJECT (layout));
+
+  return attrib_set;
+}
+
+static AtkAttributeSet *
+add_attribute (AtkAttributeSet  *attributes,
+               AtkTextAttribute  attr,
+               const gchar      *value)
+{
+  AtkAttribute *at;
+
+  at = g_new (AtkAttribute, 1);
+  at->name = g_strdup (atk_text_attribute_get_name (attr));
+  at->value = g_strdup (value);
+
+  return g_slist_prepend (attributes, at);
+}
+
+static AtkAttributeSet *
+gtk_text_cell_accessible_get_default_attributes (AtkText *text)
+{
+  AtkAttributeSet *attrib_set = NULL;
+  PangoLayout *layout;
+  GtkWidget *widget;
+
+  layout = create_pango_layout (GTK_TEXT_CELL_ACCESSIBLE (text));
+  widget = get_widget (GTK_TEXT_CELL_ACCESSIBLE (text));
+
+  attrib_set = add_attribute (attrib_set, ATK_TEXT_ATTR_DIRECTION,
+                   atk_text_attribute_get_value (ATK_TEXT_ATTR_DIRECTION,
+                                                 gtk_widget_get_direction (widget)));
+  attrib_set = _gtk_pango_get_default_attributes (NULL, layout);
+
+  attrib_set = _gtk_style_context_get_attributes (attrib_set,
+                                                  gtk_widget_get_style_context (widget),
+                                                  gtk_widget_get_state_flags (widget));
+
+  g_object_unref (G_OBJECT (layout));
+
+  return attrib_set;
+}
+
+GtkWidget *
+get_widget (GtkTextCellAccessible *text)
+{
+  AtkObject *parent;
+
+  parent = atk_object_get_parent (ATK_OBJECT (text));
+  if (GTK_IS_CONTAINER_CELL_ACCESSIBLE (parent))
+    parent = atk_object_get_parent (parent);
+
+  return gtk_accessible_get_widget (GTK_ACCESSIBLE (parent));
+}
+
+/* This function is used by gtk_text_cell_accessible_get_offset_at_point()
+ * and gtk_text_cell_accessible_get_character_extents(). There is no
+ * cached PangoLayout so we must create a temporary one using this function.
+ */
+static PangoLayout *
+create_pango_layout (GtkTextCellAccessible *text)
+{
+  GdkRGBA *foreground_rgba;
+  PangoAttrList *attr_list, *attributes;
+  PangoLayout *layout;
+  PangoUnderline uline, underline;
+  PangoFontMask mask;
+  PangoFontDescription *font_desc;
+  gboolean foreground_set, strikethrough_set, strikethrough;
+  gboolean scale_set, underline_set, rise_set;
+  gchar *renderer_text;
+  gdouble scale;
+  gint rise;
+  GtkRendererCellAccessible *gail_renderer;
+  GtkCellRendererText *gtk_renderer;
+
+  gail_renderer = GTK_RENDERER_CELL_ACCESSIBLE (text);
+  gtk_renderer = GTK_CELL_RENDERER_TEXT (gail_renderer->renderer);
+
+  g_object_get (gtk_renderer,
+                "text", &renderer_text,
+                "attributes", &attributes,
+                "foreground-set", &foreground_set,
+                "foreground-rgba", &foreground_rgba,
+                "strikethrough-set", &strikethrough_set,
+                "strikethrough", &strikethrough,
+                "font-desc", &font_desc,
+                "scale-set", &scale_set,
+                "scale", &scale,
+                "underline-set", &underline_set,
+                "underline", &underline,
+                "rise-set", &rise_set,
+                "rise", &rise,
+                NULL);
+
+  layout = gtk_widget_create_pango_layout (get_widget (text), renderer_text);
+
+  if (attributes)
+    attr_list = pango_attr_list_copy (attributes);
+  else
+    attr_list = pango_attr_list_new ();
+
+  if (foreground_set)
+    {
+      add_attr (attr_list, pango_attr_foreground_new (foreground_rgba->red * 65535,
+                                                      foreground_rgba->green * 65535,
+                                                      foreground_rgba->blue * 65535));
+    }
+
+  if (strikethrough_set)
+    add_attr (attr_list,
+              pango_attr_strikethrough_new (strikethrough));
+
+  mask = pango_font_description_get_set_fields (font_desc);
+
+  if (mask & PANGO_FONT_MASK_FAMILY)
+    add_attr (attr_list,
+      pango_attr_family_new (pango_font_description_get_family (font_desc)));
+
+  if (mask & PANGO_FONT_MASK_STYLE)
+    add_attr (attr_list, pango_attr_style_new (pango_font_description_get_style (font_desc)));
+
+  if (mask & PANGO_FONT_MASK_VARIANT)
+    add_attr (attr_list, pango_attr_variant_new (pango_font_description_get_variant (font_desc)));
+
+  if (mask & PANGO_FONT_MASK_WEIGHT)
+    add_attr (attr_list, pango_attr_weight_new (pango_font_description_get_weight (font_desc)));
+
+  if (mask & PANGO_FONT_MASK_STRETCH)
+    add_attr (attr_list, pango_attr_stretch_new (pango_font_description_get_stretch (font_desc)));
+
+  if (mask & PANGO_FONT_MASK_SIZE)
+    add_attr (attr_list, pango_attr_size_new (pango_font_description_get_size (font_desc)));
+
+  if (scale_set && scale != 1.0)
+    add_attr (attr_list, pango_attr_scale_new (scale));
+
+  if (underline_set)
+    uline = underline;
+  else
+    uline = PANGO_UNDERLINE_NONE;
+
+  if (uline != PANGO_UNDERLINE_NONE)
+    add_attr (attr_list,
+              pango_attr_underline_new (underline));
+
+  if (rise_set)
+    add_attr (attr_list, pango_attr_rise_new (rise));
+
+  pango_layout_set_attributes (layout, attr_list);
+  pango_layout_set_width (layout, -1);
+  pango_attr_list_unref (attr_list);
+
+  pango_font_description_free (font_desc);
+  pango_attr_list_unref (attributes);
+  g_free (renderer_text);
+  gdk_rgba_free (foreground_rgba);
+
+  return layout;
+}
+
+static void
+add_attr (PangoAttrList *attr_list,
+         PangoAttribute *attr)
+{
+  attr->start_index = 0;
+  attr->end_index = G_MAXINT;
+  pango_attr_list_insert (attr_list, attr);
+}
+
+
+static void
+get_origins (GtkWidget *widget,
+             gint      *x_window,
+             gint      *y_window,
+             gint      *x_toplevel,
+             gint      *y_toplevel)
+{
+  GdkWindow *window;
+
+  if (GTK_IS_TREE_VIEW (widget))
+    window = gtk_tree_view_get_bin_window (GTK_TREE_VIEW (widget));
+  else
+    window = gtk_widget_get_window (widget);
+
+  gdk_window_get_origin (window, x_window, y_window);
+  window = gdk_window_get_toplevel (gtk_widget_get_window (widget));
+  gdk_window_get_origin (window, x_toplevel, y_toplevel);
+}
+
+static void
+gtk_text_cell_accessible_get_character_extents (AtkText      *text,
+                                                gint          offset,
+                                                gint         *x,
+                                                gint         *y,
+                                                gint         *width,
+                                                gint         *height,
+                                                AtkCoordType  coords)
+{
+  GtkRendererCellAccessible *gail_renderer;
+  GtkRequisition min_size;
+  GtkCellRendererText *gtk_renderer;
+  GdkRectangle rendered_rect;
+  GtkWidget *widget;
+  AtkObject *parent;
+  PangoRectangle char_rect;
+  PangoLayout *layout;
+  gchar *renderer_text;
+  gfloat xalign, yalign;
+  gint x_offset, y_offset, index;
+  gint xpad, ypad;
+  gint x_window, y_window, x_toplevel, y_toplevel;
+
+  if (!GTK_TEXT_CELL_ACCESSIBLE (text)->cell_text)
+    {
+      *x = *y = *height = *width = 0;
+      return;
+    }
+  if (offset < 0 || offset >= GTK_TEXT_CELL_ACCESSIBLE (text)->cell_length)
+    {
+      *x = *y = *height = *width = 0;
+      return;
+    }
+  gail_renderer = GTK_RENDERER_CELL_ACCESSIBLE (text);
+  gtk_renderer = GTK_CELL_RENDERER_TEXT (gail_renderer->renderer);
+
+  g_object_get (gtk_renderer, "text", &renderer_text, NULL);
+  if (text == NULL)
+    {
+      g_free (renderer_text);
+      return;
+    }
+
+  parent = atk_object_get_parent (ATK_OBJECT (text));
+  if (GTK_IS_CONTAINER_CELL_ACCESSIBLE (parent))
+    parent = atk_object_get_parent (parent);
+  widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (parent));
+  g_return_if_fail (GAIL_IS_CELL_PARENT (parent));
+  gail_cell_parent_get_cell_area (GAIL_CELL_PARENT (parent), GTK_CELL_ACCESSIBLE (text),
+                                  &rendered_rect);
+
+  gtk_cell_renderer_get_preferred_size (GTK_CELL_RENDERER (gtk_renderer),
+                                        widget,
+                                        &min_size, NULL);
+
+  gtk_cell_renderer_get_alignment (GTK_CELL_RENDERER (gtk_renderer), &xalign, &yalign);
+  if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
+    xalign = 1.0 - xalign;
+  x_offset = MAX (0, xalign * (rendered_rect.width - min_size.width));
+  y_offset = MAX (0, yalign * (rendered_rect.height - min_size.height));
+
+  layout = create_pango_layout (GTK_TEXT_CELL_ACCESSIBLE (text));
+
+  index = g_utf8_offset_to_pointer (renderer_text, offset) - renderer_text;
+  pango_layout_index_to_pos (layout, index, &char_rect);
+
+  gtk_cell_renderer_get_padding (gail_renderer->renderer, &xpad, &ypad);
+
+  get_origins (widget, &x_window, &y_window, &x_toplevel, &y_toplevel);
+
+  *x = (char_rect.x / PANGO_SCALE) + x_offset + rendered_rect.x + xpad + x_window;
+  *y = (char_rect.y / PANGO_SCALE) + y_offset + rendered_rect.y + ypad + y_window;
+  *height = char_rect.height / PANGO_SCALE;
+  *width = char_rect.width / PANGO_SCALE;
+
+  if (coords == ATK_XY_WINDOW)
+    {
+      *x -= x_toplevel;
+      *y -= y_toplevel;
+    }
+  else if (coords != ATK_XY_SCREEN)
+    {
+      *x = 0;
+      *y = 0;
+      *height = 0;
+      *width = 0;
+    }
+
+  g_free (renderer_text);
+  g_object_unref (layout);
+}
+
+static gint
+gtk_text_cell_accessible_get_offset_at_point (AtkText      *text,
+                                              gint          x,
+                                              gint          y,
+                                              AtkCoordType  coords)
+{
+  AtkObject *parent;
+  GtkRendererCellAccessible *gail_renderer;
+  GtkCellRendererText *gtk_renderer;
+  GtkRequisition min_size;
+  GtkWidget *widget;
+  GdkRectangle rendered_rect;
+  PangoLayout *layout;
+  gchar *renderer_text;
+  gfloat xalign, yalign;
+  gint x_offset, y_offset, index;
+  gint xpad, ypad;
+  gint x_window, y_window, x_toplevel, y_toplevel;
+  gint x_temp, y_temp;
+  gboolean ret;
+
+  if (!GTK_TEXT_CELL_ACCESSIBLE (text)->cell_text)
+    return -1;
+
+  gail_renderer = GTK_RENDERER_CELL_ACCESSIBLE (text);
+  gtk_renderer = GTK_CELL_RENDERER_TEXT (gail_renderer->renderer);
+  parent = atk_object_get_parent (ATK_OBJECT (text));
+
+  g_object_get (gtk_renderer, "text", &renderer_text, NULL);
+  if (text == NULL)
+    {
+      g_free (renderer_text);
+      return -1;
+    }
+
+  if (GTK_IS_CONTAINER_CELL_ACCESSIBLE (parent))
+    parent = atk_object_get_parent (parent);
+
+  widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (parent));
+
+  g_return_val_if_fail (GAIL_IS_CELL_PARENT (parent), -1);
+  gail_cell_parent_get_cell_area (GAIL_CELL_PARENT (parent), GTK_CELL_ACCESSIBLE (text),
+                                  &rendered_rect);
+
+  gtk_cell_renderer_get_preferred_size (GTK_CELL_RENDERER (gtk_renderer),
+                                        widget,
+                                        &min_size, NULL);
+  gtk_cell_renderer_get_alignment (GTK_CELL_RENDERER (gtk_renderer), &xalign, &yalign);
+  if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
+    xalign = 1.0 - xalign;
+  x_offset = MAX (0, xalign * (rendered_rect.width - min_size.width));
+  y_offset = MAX (0, yalign * (rendered_rect.height - min_size.height));
+
+  layout = create_pango_layout (GTK_TEXT_CELL_ACCESSIBLE (text));
+
+  gtk_cell_renderer_get_padding (gail_renderer->renderer, &xpad, &ypad);
+
+  get_origins (widget, &x_window, &y_window, &x_toplevel, &y_toplevel);
+
+  x_temp =  x - (x_offset + rendered_rect.x + xpad) - x_window;
+  y_temp =  y - (y_offset + rendered_rect.y + ypad) - y_window;
+  if (coords == ATK_XY_WINDOW)
+    {
+      x_temp += x_toplevel;
+      y_temp += y_toplevel;
+    }
+  else if (coords != ATK_XY_SCREEN)
+    index = -1;
+
+  ret = pango_layout_xy_to_index (layout,
+                                  x_temp * PANGO_SCALE,
+                                  y_temp * PANGO_SCALE,
+                                  &index, NULL);
+  if (!ret)
+    {
+      if (x_temp < 0 || y_temp < 0)
+        index = 0;
+      else
+        index = -1;
+    }
+
+  g_object_unref (layout);
+  if (index == -1)
+    {
+      if (coords == ATK_XY_WINDOW || coords == ATK_XY_SCREEN)
+        {
+          glong length;
+
+          length = g_utf8_strlen (renderer_text, -1);
+          g_free (renderer_text);
+
+          return length;
+        }
+
+      g_free (renderer_text);
+
+      return index;
+    }
+  else
+    {
+      glong offset;
+
+      offset = g_utf8_pointer_to_offset (renderer_text,
+                                         renderer_text + index);
+      g_free (renderer_text);
+
+      return offset;
+    }
+}
+
+static gunichar
+gtk_text_cell_accessible_get_character_at_offset (AtkText *text,
+                                                  gint     offset)
+{
+  gchar *index;
+  gchar *string;
+
+  string = GTK_TEXT_CELL_ACCESSIBLE(text)->cell_text;
+
+  if (!string)
+    return '\0';
+
+  if (offset >= g_utf8_strlen (string, -1))
+    return '\0';
+
+  index = g_utf8_offset_to_pointer (string, offset);
+
+  return g_utf8_get_char (index);
+}
+
+static void
+atk_text_interface_init (AtkTextIface *iface)
+{
+  iface->get_text = gtk_text_cell_accessible_get_text;
+  iface->get_character_at_offset = gtk_text_cell_accessible_get_character_at_offset;
+  iface->get_text_before_offset = gtk_text_cell_accessible_get_text_before_offset;
+  iface->get_text_at_offset = gtk_text_cell_accessible_get_text_at_offset;
+  iface->get_text_after_offset = gtk_text_cell_accessible_get_text_after_offset;
+  iface->get_character_count = gtk_text_cell_accessible_get_character_count;
+  iface->get_caret_offset = gtk_text_cell_accessible_get_caret_offset;
+  iface->set_caret_offset = gtk_text_cell_accessible_set_caret_offset;
+  iface->get_run_attributes = gtk_text_cell_accessible_get_run_attributes;
+  iface->get_default_attributes = gtk_text_cell_accessible_get_default_attributes;
+  iface->get_character_extents = gtk_text_cell_accessible_get_character_extents;
+  iface->get_offset_at_point = gtk_text_cell_accessible_get_offset_at_point;
+}
diff --git a/gtk/a11y/gtktextcellaccessible.h b/gtk/a11y/gtktextcellaccessible.h
new file mode 100644 (file)
index 0000000..536aef8
--- /dev/null
@@ -0,0 +1,56 @@
+/* GAIL - The GNOME Accessibility Enabling Library
+ * Copyright 2001 Sun Microsystems Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GTK_TEXT_CELL_ACCESSIBLE_H__
+#define __GTK_TEXT_CELL_ACCESSIBLE_H__
+
+#include <atk/atk.h>
+#include "gtkrenderercellaccessible.h"
+
+G_BEGIN_DECLS
+
+#define GTK_TYPE_TEXT_CELL_ACCESSIBLE            (gtk_text_cell_accessible_get_type ())
+#define GTK_TEXT_CELL_ACCESSIBLE(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_TEXT_CELL_ACCESSIBLE, GtkTextCellAccessible))
+#define GTK_TEXT_CELL_ACCESSIBLE_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TEXT_CELL_ACCESSIBLE, GtkTextCellAccessibleClass))
+#define GTK_IS_TEXT_CELL_ACCESSIBLE(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_TEXT_CELL_ACCESSIBLE))
+#define GTK_IS_TEXT_CELL_ACCESSIBLE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_TEXT_CELL_ACCESSIBLE))
+#define GTK_TEXT_CELL_ACCESSIBLE_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_TEXT_CELL_ACCESSIBLE, GtkTextCellAccessibleClass))
+
+typedef struct _GtkTextCellAccessible      GtkTextCellAccessible;
+typedef struct _GtkTextCellAccessibleClass GtkTextCellAccessibleClass;
+
+struct _GtkTextCellAccessible
+{
+  GtkRendererCellAccessible parent;
+  gchar *cell_text;
+  gint caret_pos;
+  gint cell_length;
+};
+
+struct _GtkTextCellAccessibleClass
+{
+  GtkRendererCellAccessibleClass parent_class;
+};
+
+GType      _gtk_text_cell_accessible_get_type (void);
+AtkObject *_gtk_text_cell_accessible_new      (void);
+
+G_END_DECLS
+
+#endif /* __GTK_TEXT_CELL_ACCESSIBLE_H__ */
index 53afb8dc6b0cf895a1190f1c6888ff0d82f25ee3..fad9bf9f3db1fca46cfc239a23b1a36f1d17f993 100644 (file)
@@ -29,7 +29,7 @@
 #include "gtkbooleancellaccessible.h"
 #include "gtkimagecellaccessible.h"
 #include "gtkcontainercellaccessible.h"
-#include "gailtextcell.h"
+#include "gtktextcellaccessible.h"
 #include "gailcellparent.h"
 
 typedef struct _GtkTreeViewAccessibleCellInfo  GtkTreeViewAccessibleCellInfo;
@@ -578,7 +578,7 @@ gtk_tree_view_accessible_ref_child (AtkObject *obj,
       GtkCellRenderer *fake_renderer;
 
       fake_renderer = g_object_new (GTK_TYPE_CELL_RENDERER_TEXT, NULL);
-      child = gail_text_cell_new ();
+      child = _gtk_text_cell_accessible_new ();
       cell = GTK_CELL_ACCESSIBLE (child);
       renderer_cell = GTK_RENDERER_CELL_ACCESSIBLE (child);
       renderer_cell->renderer = fake_renderer;
@@ -607,7 +607,7 @@ gtk_tree_view_accessible_ref_child (AtkObject *obj,
           if (GTK_IS_CELL_RENDERER_TEXT (renderer))
             {
               g_object_get (G_OBJECT (renderer), "editable", &editable, NULL);
-              child = gail_text_cell_new ();
+              child = _gtk_text_cell_accessible_new ();
             }
           else if (GTK_IS_CELL_RENDERER_TOGGLE (renderer))
             child = _gtk_boolean_cell_accessible_new ();